package cn.com.acca.ma.service.impl;

import cn.com.acca.ma.common.util.PropertiesUtil;
import cn.com.acca.ma.enumeration.PythonApiResult;
import cn.com.acca.ma.model.MacroChinaGDP;
import cn.com.acca.ma.model.ModelAllGoldCross;
import cn.com.acca.ma.service.MacroChinaGDPService;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.ui.RectangleInsets;

import java.awt.*;
import java.io.*;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

public class MacroChinaGDPServiceImpl extends BaseServiceImpl<MacroChinaGDPServiceImpl, ModelAllGoldCross> implements
        MacroChinaGDPService {

    /**
     * 如果空，则插入记录
     */
    @Override
    public void writeGDPIfNone() {
        String filePath = PropertiesUtil.getValue(MACROS_CHINA_GDP_PROPERTIES,"adam3.api.file.path");
        String writeGdpIfNone = PropertiesUtil.getValue(MACROS_CHINA_GDP_PROPERTIES,"adam3.api.method.writeGdpIfNone");

        logger.info("调用adam3接口，插入或更新macro_china_gdp表");

        Process process = null;
        BufferedReader in = null;
        try {
            // 调用adam3的接口，更新股票名称
            String[] parameterArray = new String[]{"python", filePath, "api", writeGdpIfNone};
            process = Runtime.getRuntime().exec(parameterArray);
            in = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
            StringBuffer stringBuffer = new StringBuffer();
            String actionStr;
            while ((actionStr = in.readLine()) != null) {
                stringBuffer.append(actionStr);
                logger.debug("接口返回值：" + actionStr);
            }
            if (!PythonApiResult.FINISH.getCode().equals(stringBuffer.toString())){
                logger.warn("调用adam3接口，插入或更新macro_china_gdp表，返回值：" + stringBuffer);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 创建巴菲特指标图片
     */
    @Override
    public void createBuffettIndicatorPicture() {
        logger.info("创建巴菲特指标图片");

        JFreeChart jfreechart;

        // 查询年份
        List<String> yearList = macroChinaGDPDao.orderByDistinctYearList();
        // 每个季度的最后日期
        List<String> quarterEndList = new ArrayList<String>();
        quarterEndList.add("0331");
        quarterEndList.add("0630");
        quarterEndList.add("0930");
        quarterEndList.add("1231");
        // 拼接macro_china_gdp表的quarter字段
        List<String> quarterValueList = new ArrayList<>();
        // 拼接每个季度末的日期
        List<String> allQuarterEndList = new ArrayList<>();
        if (null != yearList && yearList.size() > 0){
            for (String year: yearList){
                allQuarterEndList.add(year + quarterEndList.get(0));
                allQuarterEndList.add(year + quarterEndList.get(1));
                allQuarterEndList.add(year + quarterEndList.get(2));
                allQuarterEndList.add(year + quarterEndList.get(3));

                quarterValueList.add(year + "年第1季度");
                quarterValueList.add(year + "年第1-2季度");
                quarterValueList.add(year + "年第1-3季度");
                quarterValueList.add(year + "年第1-4季度");
            }
        }

        // 查询每个季度的最后一个交易日
        List<String> realQuarterEndList = new ArrayList<>();
        if (null != allQuarterEndList && allQuarterEndList.size() > 0){
            for (String allQuarterEnd: allQuarterEndList){
                String endDate = stockMonthDao.findLessOrEqualByEndDate(allQuarterEnd);
                realQuarterEndList.add(endDate);
            }
        }

        TimeSeries totalMarketValueDivideGDPSeries = new TimeSeries("股市总市值/GDP", org.jfree.data.time.Day.class);
        TimeSeries averageClosePriceSeries = new TimeSeries("平均股价", org.jfree.data.time.Day.class);
        TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();

        for (int i = 0; i < realQuarterEndList.size(); i++) {
            String[] str = realQuarterEndList.get(i).toString().split("-");
            int year = Integer.parseInt(str[0]);
            int month = Integer.parseInt(str[1]);
            int day = Integer.parseInt(str[2]);

            // 巴菲特指标=股市总市值/GDP
            Double sumTotalMarketValue = stockTransactionDataDao.getSumTotalMarketValue(false, realQuarterEndList.get(i).replace("-", ""));
            MacroChinaGDP macroChinaGDP = macroChinaGDPDao.findByQuarter(quarterValueList.get(i));
            if (null == macroChinaGDP){
                break;
            }
            BigDecimal gdp = null;
            if (macroChinaGDP.getQuarter().contains("年第1季度")){
                gdp = macroChinaGDP.getGdpAbsoluteValue().multiply(new BigDecimal(4));
            }
            if (macroChinaGDP.getQuarter().contains("年第1-2季度")){
                gdp = macroChinaGDP.getGdpAbsoluteValue().multiply(new BigDecimal(2));
            }
            if (macroChinaGDP.getQuarter().contains("年第1-3季度")){
                gdp = macroChinaGDP.getGdpAbsoluteValue().divide(new BigDecimal(3), BigDecimal.ROUND_CEILING).multiply(new BigDecimal(4));
            }
            if (macroChinaGDP.getQuarter().contains("年第1-4季度")){
                gdp = macroChinaGDP.getGdpAbsoluteValue();
            }
            double totalMarketValueDivideGDPValue = (sumTotalMarketValue/1000000000000L) / (gdp.doubleValue()/10000) * 100;
            totalMarketValueDivideGDPSeries.add(new Day(day, month, year), totalMarketValueDivideGDPValue);

            // 平均股价
            String averageClosePrice = stockTransactionDataDao.getAverageClosePrice(false, realQuarterEndList.get(i).replace("-", ""));
            double averageClosePriceValue = Double.valueOf(averageClosePrice);
            averageClosePriceSeries.add(new Day(day, month, year), averageClosePriceValue);
        }

        timeSeriesCollection.addSeries(totalMarketValueDivideGDPSeries);
        timeSeriesCollection.addSeries(averageClosePriceSeries);

        jfreechart = ChartFactory.createTimeSeriesChart("股市总市值/GDP & 平均股价",
                "Date", "Value", timeSeriesCollection, true, true, true);
        jfreechart.setBackgroundPaint(Color.white);
        XYPlot xyplot = (XYPlot) jfreechart.getPlot();
        xyplot.setBackgroundPaint(Color.lightGray);
        xyplot.setDomainGridlinePaint(Color.white);
        xyplot.setRangeGridlinePaint(Color.white);
        xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));
        xyplot.setDomainCrosshairVisible(true);
        xyplot.setRangeCrosshairVisible(true);
        org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();
        if (xyitemrenderer instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyitemrenderer;
            xylineandshaperenderer.setBaseShapesVisible(true);
            xylineandshaperenderer.setBaseShapesFilled(true);
            xylineandshaperenderer.setSeriesPaint(2, Color.BLACK);
        }
        DateAxis dateaxis = (DateAxis) xyplot.getDomainAxis();
        dateaxis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));

        try {
            FileOutputStream fos = new FileOutputStream(PICTURE_PATH + "total_market_value_divide_gdp_and_average_close_price/" + realQuarterEndList.get(0) + "-" + realQuarterEndList.get(realQuarterEndList.size() - 1) + PICTURE_FORMAT);
            // 将统计图标输出成JPG文件
            ChartUtilities.writeChartAsJPEG(fos, // 输出到哪个输出流
                    1, // JPEG图片的质量，0~1之间
                    jfreechart, // 统计图标对象
                    imageWidth, // 宽
                    IMAGE_HEIGHT, // 高
                    null // ChartRenderingInfo 信息
            );
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String listToString(List list) {
        return null;
    }
}
